在 C 語言中,當我們需要儲存一系列相同型態的資料時,陣列 (Array) 就成為一個不可或缺的工具。而字串 (String) 在 C 語言中則是一種特殊的陣列,專門用來處理文字資料。並說明如何利用 sizeof() 來檢查記憶體大小
陣列是一個由相同資料型態的元素組成的集合,這些元素在記憶體中是連續存放的。我們可以透過索引 (Index) 來存取陣列中的每一個元素。
一維陣列是最基本的陣列形式,可以想像成一列連續的儲存格。
#include<stdio.h>
int main() {
    // 方法一:宣告時同時初始化
    int i_ary[] = {1, 2, 3};
    printf("i_ary 的內容為:%d %d %d\n", i_ary[0], i_ary[1], i_ary[2]);
    // 方法二:先宣告大小,再逐一賦值
    int i_ary2[4];
    i_ary2[0] = 5;
    i_ary2[1] = 10;
    i_ary2[2] = 15;
    i_ary2[3] = 20;
    printf("i_ary2 的內容為:%d %d %d %d\n", i_ary2[0], i_ary2[1], i_ary2[2], i_ary2[3]);
    // 使用 sizeof 運算子取得陣列在記憶體中的總大小 (位元組)
    printf("i_ary 的大小:%d bytes, i_ary2 的大小:%d bytes\n", sizeof(i_ary), sizeof(i_ary2));
    return 0;
}
宣告與初始化:
int i_ary[] = {1, 2, 3}; 所示,我們可以在宣告時使用大括號 {} 提供初始值。此時,編譯器會根據初始值的數量自動計算陣列的大小(此例中為 3)。或者,我們可以像 int i_ary2[4]; 這樣,明確指定陣列的大小。宣告後,可以透過索引單獨為每個元素賦值。索引 (Index):
sizeof 運算子:
sizeof(i_ary) 會回傳總共佔用的位元組數(3 個 int = 12 位元組)。sizeof(i_ary) 的結果會是 3 (元素個數) * 4 (每個 int 的大小) = 12。sizeof(i_ary2) 的結果會是 4 (元素個數) * 4 (每個 int 的大小) = 16。二維陣列可以視為「陣列的陣列」,常被用來模擬表格或矩陣結構,具有列 (rows) 和行 (columns) 的概念,而二維陣列 int arr[rows][cols] 記憶體中是 row-major 儲存(列優先)。
#include<stdio.h>
int main() {
    // 宣告一個 4 列 3 行的二維陣列並初始化
    int i_ary2D[4][3] = {
        {1, 2, 3}, 
        {4, 5, 6}, 
        {7, 8, 9}, 
        {10, 11, 12}
    };
    printf("i_ary2D 的內容:\n%d %d %d \n%d %d %d \n%d %d %d \n%d %d %d \n",
           i_ary2D[0][0], i_ary2D[0][1], i_ary2D[0][2],
           i_ary2D[1][0], i_ary2D[1][1], i_ary2D[1][2],
           i_ary2D[2][0], i_ary2D[2][1], i_ary2D[2][2], 
           i_ary2D[3][0], i_ary2D[3][1], i_ary2D[3][2]);
    // 宣告一個 3 列 3 行的二維陣列並逐一賦值
    int i_ary2D_2[3][3];
    i_ary2D_2[0][0] = 2; i_ary2D_2[0][1] = 4; i_ary2D_2[0][2] = 6;
    i_ary2D_2[1][0] = 8; i_ary2D_2[1][1] = 10; i_ary2D_2[1][2] = 12;
    i_ary2D_2[2][0] = 14; i_ary2D_2[2][1] = 16; i_ary2D_2[2][2] = 18;
    printf("\ni_ary2D_2 的內容:\n%d %d %d \n%d %d %d \n%d %d %d \n", 
           i_ary2D_2[0][0], i_ary2D_2[0][1], i_ary2D_2[0][2],
           i_ary2D_2[1][0], i_ary2D_2[1][1], i_ary2D_2[1][2],
           i_ary2D_2[2][0], i_ary2D_2[2][1], i_ary2D_2[2][2]);
    // 取得二維陣列的總大小
    printf("\ni_ary2D_2 的大小:%d bytes\n", sizeof(i_ary2D_2));
    return 0;
}
二維陣列規則宣告與存取:
sizeof 運算子:
sizeof 同樣會回傳整個陣列所佔用的總位元組數。sizeof(i_ary2D_2) 的結果會是 3 (列數) * 3 (行數) * 4 (每個 int 的大小) = 36。📝 i_ary2D[4][3] 記憶體配置如下:
i_ary2D:  [0][0] [0][1] [0][2]
          [1][0] [1][1] [1][2]
          [2][0] [2][1] [2][2]
          [3][0] [3][1] [3][2]
#include<stdio.h>
int main() {
    // 使用字串字面值初始化字元陣列
    char c_str[] = "Hello, World!";
    
    // 使用 %s 輸出整個字串
    printf("字串內容:%s \n", c_str);
    
    // 字串本身也是陣列,可用索引存取單一字元
    printf("第1個字元:%c, 第8個字元:%c \n", c_str[0], c_str[7]);
    
    // 計算字串陣列的大小,字串後方自動補上 '\0'
    printf("c_str 陣列的大小:%d bytes\n", sizeof(c_str));
    // 字串陣列 (二維字元陣列)
    char c_str_2D[3][4] = {"abc", "def", "ghi"};
    printf("\n字串陣列內容:\n%s\n%s\n%s\n", c_str_2D[0], c_str_2D[1], c_str_2D[2]);
    return 0;
}
}
宣告與空元字元 \0:
\0 null 終止字元 結尾。c_str 陣列的實際內容是 H, e, l, l, o, ,,  , W, o, r, l, d, !, \0。sizeof 與字串:
\0 的存在,sizeof(c_str) 的結果會是字元數量再加 1。"Hello, World!" 共有 13 個字元,加上結尾的 \0,所以 sizeof(c_str) 的結果是 14 (bytes)。這就是您註解中提到的「字串後方要多個空間」的原因,該空間就是為了存放 \0。printf 的 %s:
printf 遇到 %s 格式控制符號時,它會從指定的記憶體位址開始,逐一印出字元,直到遇到 \0 為止。\0 本身不會被印出來。字串陣列:
char c_str_2D[3][4]。[3] 代表可以儲存 3 個字串,[4] 代表每個字串的最大長度是 3 個字元,因為還需要保留 1 個空間給 \0。如果試圖存入像 "abcd" 這樣長度為 4 的字串,就會因為沒有空間存放 \0 而導致錯誤。🖼️ 圖示:"abc" 在記憶體中的配置
索引:   [0]  [1]  [2]  [3]
內容:   'a'  'b'  'c'  '\0'
👀 注意:若未預留 \0,使用 %s 輸出將導致未定行為(可能繼續讀到亂碼)。